#pragma once
#include<functional>

namespace MoYu
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr)
			:_ptr(ptr)
			,_pcount(new int(1))
		{}

		shared_ptr(const shared_ptr<T>& sptr)
			:_ptr(sptr._ptr)
			,_pcount(sptr._pcount)
		{
			++(*_pcount);
		}

		template<class D>
		shared_ptr(T* ptr , D del)
			:_ptr(ptr)
			, _pcount(new int(1))
			, func(del)
		{}

		T* get()
		{
			return _ptr;
		}

		int use_count()
		{
			return *_pcount;
		}

		void DLT()
		{
			if ((--(*_pcount)) == 0)
			{
				func(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			if (_ptr != sp._ptr)
			{
				DLT();
				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
			}

			return *this;
		}

		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}

		~shared_ptr()
		{
			DLT();
		}
	private:
		T* _ptr;
		int* _pcount;
		function<void(T*&)> func = [](T*& ptr)
			{
				delete ptr;
			};

	};

	template<class T>
	class weak_ptr
	{
	public:
		weak_ptr()
		{
			_ptr = nullptr;
		}
		weak_ptr(const weak_ptr<T>& ptr)
		{
			_ptr = ptr.get();
		}

		weak_ptr(shared_ptr<T>& ptr)
		{
			_ptr = ptr.get();
		}

		~weak_ptr()
		{
			
		}
	private:
		T* _ptr;
	};
}




